package uk.ac.cam.djjb2.mygame;

import java.io.IOException;
import java.util.HashSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

public class GameServerState extends BasicGameState {
	
	ServerNetManager netManager;
	ReplicaManager replicaManager;
	TileMap map;
	TileSet tileSet;
	SpriteSheet mapSheet;

	public GameServerState() {
		super();
	}
	
	@Override
	public void init(GameContainer container, StateBasedGame game)
			throws SlickException {

		try {
			netManager = new ServerNetManager(4231);
			replicaManager = new ReplicaManager(netManager);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		tileSet = new DefaultTileSet();
		
		mapSheet = new SpriteSheet("map.png", 32, 32);
		map = new TileMap(new Vector2i(64, 64), mapSheet, tileSet);
	
		for (int y = 0; y < 64; y++)
			for (int x = 0; x < 64; x++)
				map.setTileId(
						new Vector2i(x, y),
						1+(int)(Math.random()*4.0)
						);
		
		try {
			new TileMapProxy(replicaManager, map);
		} catch (ReplicationException e) {
			e.printStackTrace();
		}
		
		AttributeMap solidMap = map.getAttributeMap(DefaultTileSet.ATTR_SOLID);
		PathFinder pathFinder = new ThetaStarPathFinder(solidMap);
		AsyncPathFinder asyncPathFinder = new AsyncPathFinder();
		Future<Path> futurePath = asyncPathFinder.findPath(pathFinder, new Vector2i(2, 2), new Vector2i(50, 50));
		Path path = null;
		try {
			path = futurePath.get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
		netManager.addComponent(new ServerComponent() {
			
			@Override
			public void clientDisconnected(Client client) {
				client.setPlayer(null);
			}
			
			@Override
			public void clientConnected(Client client) {
				PlayerImpl player = new PlayerImpl();
				client.setPlayer(player);
				
				HashSet<Vector2i> tiles = new HashSet<Vector2i>();
				
				for (int y = 5; y < 15; y++) {
					for (int x = 5; x < 15; x++) {
						tiles.add(new Vector2i(x, y));
					}
				}
				
				player.setVisibleTiles(tiles);
			}
		});
	}

	@Override
	public void render(GameContainer container, StateBasedGame game, Graphics g)
			throws SlickException {
		map.render(Vector2i.ZERO, Vector2i.ZERO, map.getSize());
		
		g.drawString(
				Integer.toString(container.getWidth()) + "x"
						+ Integer.toString(container.getHeight()), 10, 25);
	}

	@Override
	public void update(GameContainer container, StateBasedGame game, int delta)
			throws SlickException {
		
		Vector2i pos = new Vector2i((int)(Math.random()*32.0), (int)(Math.random()*32.0));
		map.setTileId(pos, 1+(int)(Math.random()*4.0));
		
		try {
			netManager.processMessages();
			replicaManager.update();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InvalidMessageException e) {
			e.printStackTrace();
		}
	}

	@Override
	public int getID() {
		return 0;
	}


}
